﻿// Inner Fire 游戏引擎库
// MapBlock - 实例精灵绘制器
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：元素层（3）
// 对精灵实例进行绘制。只需要记录位置信息。其它的都是GPU计算。只有单一颜色。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-05-21

#include "map_blocks.h"
#include <enum_parser.h>
#include <graphics/transform_def.h>
#include <graphics/imath.h>

using namespace DirectX;

namespace ifire::dx {
MapBlocks::MapBlocks(DxMesh* mesh, ikit::sstr sub_mesh_name, size_t count)
    : mesh_(mesh)
    , sub_mesh_(mesh->GetSubMesh(sub_mesh_name))
    , draw_count_(static_cast<UINT>(count))
    , world(IDENTITY_4X4)
    , color(1.0f, 1.0f, 1.0f, 1.0f)
    , scale(1.0f, 1.0f, 1.0f)
    , material_(nullptr) {

}

void MapBlocks::Update(UploadBuffer<InstancedSpriteConstants>* main_buffer) {
  // 仅当项目已经发生变化时才设置
  if (frame_dirty_count == 0) {
    return;
  }

  // 用于复制主项目
  InstancedSpriteConstants constants;
  XMStoreFloat4x4(&constants.world, XMMatrixTranspose(XMLoadFloat4x4(&world)));
  constants.color = color;
  constants.scale = scale;
  main_buffer->CopyData(index, constants);

  // 其它的帧同样也要更新
  frame_dirty_count--;
}

void MapBlocks::SetBlock(size_t index, IVec3 position, IVec3 rotation,
    IVec3 scale, IVec2 tex_offset) {
  // 计算变换矩阵
  IVec pos = XMLoadFloat3(&position);
  IVec rot = imath::EulerToQuaternion(XMLoadFloat3(&rotation));
  IVec scl = XMLoadFloat3(&scale);
  auto mat = imath::BuildMat(pos, rot, scl);

  // TODO：此处应该将父级的变换矩阵也加入，但目前没有这个必要，以后需要的时候再增加

  // 填充项目
  MapBlockData data;
  XMStoreFloat4x4(&data.mat, XMMatrixTranspose(mat));
  data.tex_offset = tex_offset;

  // 将项目复制
  items_->CopyData(index, data);
}

void MapBlocks::SetData(UploadBufferPtr<MapBlockData>&& data) {
  items_ = std::move(data);
}


} // namespace ifire::dx